home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Utilities / AltPoint.cpp next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  11.5 KB  |  528 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        AltPoint.cpp
  3.  
  4.     Contains:    Alternate ODPoint, ODRect (C++ savvy)
  5.  
  6.     Owned by:    Jens Alfke
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>     5/24/96    jpa        1.1MRD: Inlined copy ctor and oper=
  13.  
  14.     In Progress:
  15.         
  16. */
  17.  
  18. #ifndef _ALTPOINT_
  19. #include "AltPoint.h"
  20. #endif
  21.  
  22. #ifndef SOM_Module_OpenDoc_Global_Types_defined
  23. #include "ODTypesM.xh"
  24. #endif
  25.  
  26. #ifndef _EXCEPT_
  27. #include "Except.h"
  28. #endif
  29.  
  30. #ifndef _ODDEBUG_
  31. #include "ODDebug.h"
  32. #endif
  33.  
  34. #ifndef _LINEOPS_
  35. #include "LineOps.h"        /* For kFixedEpsilon */
  36. #endif
  37.  
  38. #include <string.h>
  39.  
  40.  
  41. #ifdef _PLATFORM_MACINTOSH_
  42.     #ifndef __GXMATH__
  43.     #include <GXMath.h>
  44.     #endif
  45. #endif
  46.  
  47. #ifndef _ODDEBUG_
  48. #include "ODDebug.h"
  49. #endif
  50.  
  51. #pragma segment ODShape
  52.  
  53.  
  54. //==============================================================================
  55. // ODPoint
  56. //==============================================================================
  57.  
  58.  
  59. #ifdef _PLATFORM_MACINTOSH_
  60. ODPoint::ODPoint( Point qdpt )
  61. {
  62.     x = IntToFixed(qdpt.h);
  63.     y = IntToFixed(qdpt.v);
  64. }
  65. #endif
  66.  
  67.  
  68. #ifdef _PLATFORM_MACINTOSH_
  69. ODPoint& ODPoint::operator= ( const Point &pt )
  70. {
  71.     x = IntToFixed(pt.h);
  72.     y = IntToFixed(pt.v);
  73.     return *this;
  74. }
  75. #endif
  76.  
  77.  
  78. void ODPoint::Offset ( ODCoordinate xx, ODCoordinate yy )
  79. {
  80.     x += xx;
  81.     y += yy;
  82. }
  83.  
  84.  
  85. void ODPoint::operator+= ( const ODPoint &pt )
  86. {
  87.     x += pt.x;
  88.     y += pt.y;
  89. }
  90.  
  91.  
  92. void ODPoint::operator-= ( const ODPoint &pt )
  93. {
  94.     x -= pt.x;
  95.     y -= pt.y;
  96. }
  97.  
  98.  
  99. #ifdef _PLATFORM_MACINTOSH_
  100. void ODPoint::operator+= ( const Point &pt )
  101. {
  102.     x += IntToFixed(pt.h);
  103.     y += IntToFixed(pt.v);
  104. }
  105.  
  106.  
  107. void ODPoint::operator-= ( const Point &pt )
  108. {
  109.     x -= IntToFixed(pt.h);
  110.     y -= IntToFixed(pt.v);
  111. }
  112.  
  113. Point
  114. ODPoint::AsQDPoint( ) const
  115. {
  116.     Point pt;
  117.     pt.h = FixedToInt(x);
  118.     pt.v = FixedToInt(y);
  119.     return pt;
  120. }
  121. #endif
  122.  
  123.  
  124. ODSShort
  125. ODPoint::IntX( ) const
  126. {
  127.     return FixedToInt(x);
  128. }
  129.  
  130.  
  131. ODSShort
  132. ODPoint::IntY( ) const
  133. {
  134.     return FixedToInt(y);
  135. }
  136.  
  137.  
  138. ODBoolean
  139. ODPoint::operator==( const ODPoint &pt ) const
  140. {
  141.     return x==pt.x && y==pt.y;
  142. }
  143.  
  144.  
  145. ODBoolean
  146. ODPoint::operator!=( const ODPoint &pt ) const
  147. {
  148.     return x!=pt.x || y!=pt.y;
  149. }
  150.  
  151.  
  152. ODBoolean
  153. ODPoint::ApproxEquals( const ODPoint& pt ) const
  154. {
  155.     ODFixed delta;
  156.     delta = x-pt.x;
  157.     if( delta>kFixedEpsilon || delta<-kFixedEpsilon )
  158.         return kODFalse;
  159.     delta = y-pt.y;
  160.     if( delta>kFixedEpsilon || delta<-kFixedEpsilon )
  161.         return kODFalse;
  162.     return kODTrue;
  163. }
  164.  
  165.  
  166. //==============================================================================
  167. // ODRect
  168. //==============================================================================
  169.  
  170.  
  171. #pragma segment ODShape
  172.  
  173.  
  174. #define ASSERTVALID()        WASSERT(right>=left && bottom>=top)
  175.  
  176.  
  177. //------------------------------------------------------------------------------
  178. // ::ODRect( corner1, corner2 )
  179. //
  180. // Construct a rectangle given two opposite corners (not necessarily topLeft,botRight)
  181. //------------------------------------------------------------------------------
  182.  
  183. ODRect::ODRect( const ODPoint &a, const ODPoint &b )
  184. {
  185.     this->Set(a,b);
  186. }
  187.  
  188.  
  189. //------------------------------------------------------------------------------
  190. // ::ODRect( topLeft, width, height )
  191. //
  192. // Construct a rectangle given its origin, width and height.
  193. //------------------------------------------------------------------------------
  194.  
  195. ODRect::ODRect( const ODPoint &topLeft, ODCoordinate width, ODCoordinate height )
  196. {
  197.     WASSERT(width>=0);
  198.     WASSERT(height>=0);
  199.     
  200.     left = topLeft.x;        right = topLeft.x + width;
  201.     top  = topLeft.y;        bottom= topLeft.y + height;
  202. }
  203.  
  204.  
  205. #ifdef _PLATFORM_MACINTOSH_
  206. //------------------------------------------------------------------------------
  207. // ::ODRect( Rect )
  208. //
  209. // Construct an ODRect from a QuickDraw Rect
  210. //------------------------------------------------------------------------------
  211.  
  212. ODRect::ODRect( const Rect &r )
  213. {
  214.     left = ff(r.left);        right = ff(r.right);
  215.     top  = ff(r.top);        bottom= ff(r.bottom);
  216. }
  217.  
  218.  
  219. //------------------------------------------------------------------------------
  220. // ::= Rect
  221. //
  222. // Set an ODRect from a QuickDraw Rect
  223. //------------------------------------------------------------------------------
  224.  
  225. ODRect&
  226. ODRect:: operator= ( const Rect &r )
  227. {
  228.     left = ff(r.left);        right = ff(r.right);
  229.     top  = ff(r.top);        bottom= ff(r.bottom);
  230.     ASSERTVALID();
  231.     return *this;
  232. }
  233. #endif
  234.  
  235.  
  236. //------------------------------------------------------------------------------
  237. // ::Set
  238. //
  239. // Set all four coordinates of a rectangle. Warn if the resulting rect is bogus.
  240. //------------------------------------------------------------------------------
  241.  
  242. void
  243. ODRect::Set( ODCoordinate l, ODCoordinate t, ODCoordinate r, ODCoordinate b )
  244. {
  245.     left = l;                right = r;
  246.     top  = t;                bottom= b;
  247.     ASSERTVALID();
  248. }
  249.  
  250.  
  251. //------------------------------------------------------------------------------
  252. // ::Set
  253. //
  254. // Set all four coordinates of a rectangle. Warn if the resulting rect is bogus.
  255. //------------------------------------------------------------------------------
  256.  
  257. void
  258. ODRect::Set( const ODPoint &origin, ODCoordinate width, ODCoordinate height )
  259. {
  260.     WASSERT(width>=0);
  261.     WASSERT(height>=0);
  262.     left = origin.x;                right = left+width;
  263.     top  = origin.y;                bottom= top +height;
  264. }
  265.  
  266.  
  267. //------------------------------------------------------------------------------
  268. // ::Set
  269. //
  270. // Construct a rectangle given two opposite corners (not necessarily topLeft,botRight)
  271. //------------------------------------------------------------------------------
  272.  
  273. void
  274. ODRect::Set( const ODPoint &a, const ODPoint &b )
  275. {
  276.     if( a.x<b.x ) {
  277.         left = a.x;
  278.         right= b.x;
  279.     } else {
  280.         left = b.x;
  281.         right= a.x;
  282.     }
  283.     if( a.y<b.y ) {
  284.         top   = a.y;
  285.         bottom= b.y;
  286.     } else {
  287.         top   = b.y;
  288.         bottom= a.y;
  289.     }
  290. }
  291.  
  292.  
  293. //------------------------------------------------------------------------------
  294. // ::SetInt
  295. //
  296. // Set coordinates of a rectangle from integers. Warn if the resulting rect is bogus.
  297. //------------------------------------------------------------------------------
  298.  
  299. void
  300. ODRect::SetInt( short l, short t, short r, short b )
  301. {
  302.     left = ff(l);            right = ff(r);
  303.     top  = ff(t);            bottom= ff(b);
  304.     ASSERTVALID();
  305. }
  306.  
  307.  
  308. //------------------------------------------------------------------------------
  309. // ::Offset
  310. //
  311. // Move a rectangle.
  312. //------------------------------------------------------------------------------
  313.  
  314. void
  315. ODRect::Offset( ODCoordinate x, ODCoordinate y )
  316. {
  317.     left += x;                right += x;
  318.     top  += y;                bottom+= y;
  319. }
  320.  
  321. void
  322. ODRect::Offset( const ODPoint &pt )
  323. {
  324.     left += pt.x;            right += pt.x;
  325.     top  += pt.y;            bottom+= pt.y;
  326. }
  327.  
  328.  
  329. //------------------------------------------------------------------------------
  330. // ::Inset
  331. //
  332. // Inset the edges of a rectangle, without collapsing to negative dimensions.
  333. //------------------------------------------------------------------------------
  334.  
  335. void
  336. ODRect::Inset( ODCoordinate x, ODCoordinate y )
  337. {
  338.     left += x;
  339.     right = Max(left,right-x);
  340.     top += y;
  341.     bottom = Max(top,bottom-y);
  342. }
  343.  
  344.  
  345. //------------------------------------------------------------------------------
  346. // ::Clear
  347. //
  348. // Zero all coordinates
  349. //------------------------------------------------------------------------------
  350.  
  351. void
  352. ODRect::Clear( )
  353. {
  354.     left = right = top = bottom = 0;
  355. }
  356.  
  357.  
  358. //------------------------------------------------------------------------------
  359. // :: &=
  360. //
  361. // Intersect me with another rectangle (result stored in me)
  362. //------------------------------------------------------------------------------
  363.  
  364. void
  365. ODRect:: operator&= ( const ODRect &r )
  366. {
  367.     left = Max(left,r.left);    right = Min(right, r.right);
  368.     top  = Max(top, r.top);        bottom= Min(bottom,r.bottom);
  369.     if( this->IsEmpty() )
  370.         this->Clear();
  371. }
  372.  
  373.  
  374. //------------------------------------------------------------------------------
  375. // :: |=
  376. //
  377. // Union me with another rectangle (result stored in me)
  378. //------------------------------------------------------------------------------
  379.  
  380. void
  381. ODRect:: operator|= ( const ODRect &r )
  382. {
  383.     if( this->IsEmpty() )
  384.         *this = r;
  385.     else if( !r.IsEmpty() ) {
  386.         left = Min(left,r.left);
  387.         right= Max(right,r.right);
  388.         top  = Min(top,r.top);
  389.         bottom=Max(bottom,r.bottom);
  390.     }
  391. }
  392.  
  393.  
  394. //------------------------------------------------------------------------------
  395. // :: |= ODPoint
  396. //
  397. // Union me with a point (expand to fit point)
  398. //------------------------------------------------------------------------------
  399.  
  400. void
  401. ODRect:: operator|= ( const ODPoint &pt )
  402. {
  403.     left = Min(left,pt.x);
  404.     right= Max(right,pt.x);
  405.     top  = Min(top,pt.y);
  406.     bottom=Max(bottom,pt.y);
  407. }
  408.  
  409.  
  410. #ifdef _PLATFORM_MACINTOSH_
  411. //------------------------------------------------------------------------------
  412. // :: AsQDRect
  413. //
  414. // Turn me into a QuickDraw rect
  415. //------------------------------------------------------------------------------
  416.  
  417. void
  418. ODRect::AsQDRect( Rect &r ) const
  419. {
  420.     SetRect(&r, FixedToInt(left), FixedToInt(top), FixedToInt(right), FixedToInt(bottom));
  421. }
  422. #endif
  423.  
  424.  
  425. //------------------------------------------------------------------------------
  426. // :: IsEmpty
  427. //
  428. // Do I have no area?
  429. //------------------------------------------------------------------------------
  430.  
  431. Boolean
  432. ODRect::IsEmpty( ) const
  433. {
  434.     return right<=left || bottom<=top;
  435. }
  436.  
  437.  
  438. //------------------------------------------------------------------------------
  439. // :: Contains( Point )
  440. //
  441. // Do I contain a point? (Remember, I don't contain my right and bottom edges.)
  442. //------------------------------------------------------------------------------
  443.  
  444. Boolean
  445. ODRect::Contains( const ODPoint &pt ) const
  446. {
  447.     return left<=pt.x && pt.x<right
  448.         && top <=pt.y && pt.y<bottom;
  449. }
  450.  
  451.  
  452. //------------------------------------------------------------------------------
  453. // :: Contains( Rect )
  454. //
  455. // Do I contain an entire rect?
  456. //------------------------------------------------------------------------------
  457.  
  458. Boolean
  459. ODRect::Contains( const ODRect &r ) const
  460. {
  461.     if( r.right<=r.left || r.bottom<=r.top )
  462.         return kODTrue;                    // Empty rect contained in anything
  463.     else
  464.         return left<=r.left && r.right<=right
  465.             && top <=r.top  && r.bottom<=bottom;
  466. }
  467.  
  468.  
  469. //------------------------------------------------------------------------------
  470. // :: ApproxContains( Rect )
  471. //
  472. // Do I approximately (within epsilon) contain an entire rect?
  473. //------------------------------------------------------------------------------
  474.  
  475. Boolean
  476. ODRect::ApproxContains( const ODRect &r ) const
  477. {
  478.     if( r.right<=r.left || r.bottom<=r.top )
  479.         return kODTrue;                    // Empty rect contained in anything
  480.     else
  481.         return left-kFixedEpsilon<=r.left && r.right<=right+kFixedEpsilon
  482.             && top-kFixedEpsilon <=r.top  && r.bottom<=bottom+kFixedEpsilon;
  483. }
  484.  
  485.  
  486. //------------------------------------------------------------------------------
  487. // :: ==
  488. //
  489. // Am I equal to another rect?
  490. //------------------------------------------------------------------------------
  491.  
  492. Boolean
  493. ODRect::operator==( const ODRect &r ) const
  494. {
  495.     return memcmp(this,&r,sizeof(ODRect)) == 0;
  496. }
  497.  
  498.  
  499. //------------------------------------------------------------------------------
  500. // :: ApproxEquals
  501. //
  502. // Am I approximately equal (within epsilon) to another rect?
  503. //------------------------------------------------------------------------------
  504.  
  505. ODBoolean
  506. ODRect::ApproxEquals( const ODRect &r ) const
  507. {
  508.     return left-r.left<=kFixedEpsilon     && left-r.left>=-kFixedEpsilon
  509.         && right-r.right<=kFixedEpsilon   && right-r.right>=-kFixedEpsilon
  510.         && top-r.top<=kFixedEpsilon       && top-r.top>=-kFixedEpsilon
  511.         && bottom-r.bottom<=kFixedEpsilon && bottom-r.bottom>=-kFixedEpsilon;
  512. }
  513.  
  514.  
  515. //------------------------------------------------------------------------------
  516. // :: Intersects
  517. //
  518. // Do I intersect another rectangle?
  519. // (Remember, I don't contain my right and bottom edges.)
  520. //------------------------------------------------------------------------------
  521.  
  522. Boolean
  523. ODRect::Intersects( const ODRect &r ) const
  524. {
  525.     return Max(left,r.left) < Min(right,r.right)
  526.         && Max(top,r.top) < Min(bottom,r.bottom);
  527. }
  528.